package com.lock.utils

import android.app.Activity
import android.util.Log
import com.google.gson.Gson
import com.lock.utils.BleProfile.AUTH_TAG
import com.lock.utils.BleProfile.STATUS_CHECK_ERROR
import com.lock.utils.BleProfile.STATUS_CLEAN_ERROR
import com.lock.utils.BleProfile.STATUS_DOING
import com.lock.utils.BleProfile.STATUS_INVALID
import com.lock.utils.BleProfile.STATUS_LENTH_ERROR
import com.lock.utils.BleProfile.STATUS_MATCH_ERROR
import com.lock.utils.BleProfile.STATUS_NOFOUND_ERROR
import com.lock.utils.BleProfile.STATUS_ORDER_ERROR
import com.lock.utils.BleProfile.STATUS_PARAMS_ERROR
import com.lock.utils.BleProfile.STATUS_PERMISS_ERROR
import com.lock.utils.BleProfile.STATUS_PWD_ERROR
import com.lock.utils.BleProfile.STATUS_READ_ERROR
import com.lock.utils.BleProfile.STATUS_SUCCESS
import com.lock.utils.BleProfile.STATUS_TYPE_ERROR
import com.lock.utils.BleProfile.STATUS_UNDER_ERROR
import com.lock.utils.BleProfile.STATUS_VERSION_ERROR
import com.lock.utils.BleProfile.STATUS_WRITE_ERROR
import com.utils.BlueToothUtil
import com.utils.BlueToothUtil.BleConnectCallback
import com.utils.BlueToothUtil.BleNotifyCallback
import com.utils.ByteUtils
import com.utils.MD5Tool
import com.xingjibase.bean.LockMesBean


class LockBleUtils {
    companion object {
        private var LOCK_TYPE_AUTH_LOCK = "auth"                  //鉴权
        private var LOCK_TYPE_DOWN_LOCK = "unlock"                //落锁
        private var LOCK_TYPE_UP_LOCK = "lock"                    //抬锁
        private var LOCK_TYPE_REPORT_LOCK = "report"              //报告
        private var LOCK_TYPE_BEEP_LOCK = "beep"                  //蜂鸣
        private var LOCK_TYPE_DOWN_AUTO_LOCK = "unlock-auto"      //落锁（自动）
        private var LOCK_TYPE_UP_BT_LOCK = "lock-bt"              //抬锁（蓝牙）
        private var LOCK_TYPE_UP_AUTO_LOCK = "lock-auto"          //抬锁（自动）

        private var mContext: Activity? = null
        //val UUID_DESC_NOTITY = "00002902-0000-1000-8000-00805F9B34FB"

        interface BleOrderIml {
            fun success(where: String, data: String?)
            fun fail(where: String, exception: String?)
        }

        /**
         * 建立连接
         */
        fun connect(com: Activity?, msgBean: LockMesBean?, iml: BleConnectCallback) {
            mContext = com
            BlueToothUtil.getInstance()
                .setServiceUUID(msgBean?.model?.service)
                .setReadNotifyUUID(msgBean?.model?.rX_CHARACTERISTICS)
                .setWriteNotifyUUID(msgBean?.model?.tX_CHARACTERISTICS)
                //.setDescNotifyUUID(UUID_DESC_NOTITY)
                .scanConnect(com, msgBean?.localName, iml)
        }

//        fun getLockOrder(mBleMsgValue: LockMesBean?, mOrderTag: String?): String {
//            if (mBleMsgValue?.cmdAction != null) {
//                for (orderBean in mBleMsgValue.cmdAction) {
//                    if (orderBean.code != null && orderBean.code != "" && orderBean.code == mOrderTag) {
//                        return orderBean.data
//                    }
//                }
//            }
//            return ""
//        }

        /**
         * 鉴权操作
         */
        fun authBle(mBleMsgValue: LockMesBean?, order: BleOrderIml) {
            /**
             * 获取随机密码
             */
            BlueToothUtil.getInstance().write(BleProfile.authBle, object : BleNotifyCallback {
                override fun onNotifySuccess() {
                    Log.d("writeAndNotify", "onNotifySuccess")
                }

                override fun onNotifyFailure(status: Int) {
                    order.fail(AUTH_TAG, "获取随机密码失败")
                }

                override fun onCharacteristicChanged(mRandomPwd: ByteArray?) {
                    val mPreset = ByteUtils.string2Base64(mBleMsgValue?.preKey.toString())
                    val mRandom = deleteHead(mRandomPwd)
                    val mLockIdStr: ByteArray? = mBleMsgValue?.lockID?.toString()?.toByteArray()
                    val md5Pwd = authArrayMerge(mPreset, mRandom, mLockIdStr)

                    /**
                     * 鉴权
                     */
                    BlueToothUtil.getInstance().write(md5Pwd, object : BleNotifyCallback {
                        override fun onNotifySuccess() {
                            Log.d("writeAndNotify", "onNotifySuccess")
                        }

                        override fun onNotifyFailure(status: Int) {
                            order.fail(AUTH_TAG, "鉴权失败")
                        }

                        override fun onCharacteristicChanged(data: ByteArray?) {
                            if (data != null && data.size >= 3) {
                                val byteStr = ByteUtils.toHexString1(data[2])
                                val byteValue = statusCode(byteStr)
                                if (byteStr == STATUS_SUCCESS || byteStr == STATUS_DOING) {
                                    order.success(AUTH_TAG, byteValue)
                                } else {
                                    order.fail(AUTH_TAG, byteValue)
                                }
                            } else {
                                order.fail(AUTH_TAG, "鉴权失败")
                            }
                        }
                    })
                }
            })
        }

        /**
         * 地锁起降控制
         * 根据地锁当前状态判断起降
         * up==1     升锁
         * up==2     降锁
         */
        fun lockUpDown(mBleMsgValue: LockMesBean?, up: Int?, order: BleOrderIml) {
            readLockStatus(mBleMsgValue, object : BleOrderIml {
                override fun success(where: String, data: String?) {
                    val map = Gson().fromJson(data, HashMap::class.java)
                    if (up == 1) {
                        if (map["地锁状态"] == "地锁状态未知" || map["地锁状态"] == "已落锁") {
                            lockCallBack(up, mBleMsgValue, order)
                        } else {
                            order.success(BleProfile.UP_TAG, "500")
                        }
                    } else {
                        if (map["地锁状态"] == "地锁状态未知" || map["地锁状态"] == "已抬锁") {
                            lockCallBack(up, mBleMsgValue, order)
                        } else {
                            order.success(BleProfile.DOWN_TAG, "500")
                        }
                    }
                }

                override fun fail(where: String, exception: String?) {
                    order.fail(where, exception)
                }
            })
        }

        /**
         * 蜂鸣
         */
        fun beeVoice(mBleMsgValue: LockMesBean?, order: BleOrderIml) {
            val base64 = ByteUtils.string2Base64(mBleMsgValue?.cmdAction?.beep?.data)
            BlueToothUtil.getInstance().write(base64, object : BleNotifyCallback {
                override fun onNotifySuccess() {}

                override fun onNotifyFailure(status: Int) {
                    order.fail("蜂鸣", "")
                }

                override fun onCharacteristicChanged(data: ByteArray?) {
                    beemSoundResult(data, order, mBleMsgValue)
                }
            })
        }

        /**
         * 灯光控制
         */
        fun lightControl(mBleMsgValue: LockMesBean?, status: Int?, order: BleOrderIml) {

        }

        /**
         * 地锁升降状态回调
         * a==1     升锁
         * a==2     降锁
         */
        fun lockCallBack(a: Int?, mBleMsgValue: LockMesBean?, order: BleOrderIml?) {
            val mBase64 = if (a == 1) {
                ByteUtils.string2Base64(mBleMsgValue?.cmdAction?.lock?.data)
            } else {
                ByteUtils.string2Base64(mBleMsgValue?.cmdAction?.unlock?.data)
            }
            BlueToothUtil.getInstance().write(mBase64, object : BleNotifyCallback {
                override fun onNotifySuccess() {}

                override fun onNotifyFailure(status: Int) {
                    if (a == 1) {
                        order?.fail(BleProfile.UP_TAG, "")
                    } else {
                        order?.fail(BleProfile.DOWN_TAG, "")
                    }
                }

                override fun onCharacteristicChanged(data: ByteArray?) {
                    resultUpDownStatus(a, order, data, mBleMsgValue)
                }
            })
        }

        /**
         * 读取地锁状态
         */
        fun readLockStatus(mBleMsgValue: LockMesBean?, order: BleOrderIml) {
            val base64 = BleProfile.statusData
            //val base64 = ByteUtils.string2Base64(mBleMsgValue?.cmdAction?.report.toString())
            BlueToothUtil.getInstance().write(base64, object : BleNotifyCallback {
                override fun onNotifySuccess() {
                    Log.d("TAG", "onNotifySuccess")
                }

                override fun onNotifyFailure(status: Int) {
                    if (status == BlueToothUtil.BT_CONNECT_STATUS) {
                        order.fail(BleProfile.STATUS_TAG, "" + status)
                    } else {
                        order.fail(BleProfile.STATUS_TAG, "")
                    }
                }

                override fun onCharacteristicChanged(data: ByteArray?) {
                    if (mBleMsgValue?.model?.line?.toString() == BleProfile.LOCK_XJ_TAG) {              //洛可可设备
                        if (data != null && data.size >= 3) {
                            val byteStr = ByteUtils.toHexString1(data[2])
                            val byteValue = statusCode(byteStr)
                            if (byteStr == STATUS_SUCCESS || byteStr == STATUS_DOING) {
                                val statusMes = lockStatus(BleProfile.STATUS_TAG, data)
                                order.success(BleProfile.STATUS_TAG, statusMes)
                            } else {
                                order.fail(BleProfile.STATUS_TAG, byteValue)
                            }
                        } else {
                            order.fail(BleProfile.STATUS_TAG, "失败")
                        }
                    } else {                                                                                //丁丁设备
                        order.success(BleProfile.STATUS_TAG, lockStatusForDD(BleProfile.STATUS_TAG, data))
                    }
                }
            })
        }

        /**
         * 蜂鸣返回值
         */
        private fun beemSoundResult(data: ByteArray?, order: BleOrderIml, mBleMsgValue: LockMesBean?) {
            if (mBleMsgValue?.model?.line?.toString() == BleProfile.LOCK_XJ_TAG) {              //洛可可设备
                if (data != null && data.size >= 3) {
                    val byteStr = ByteUtils.toHexString1(data[2])
                    val byteValue = statusCode(byteStr)
                    if (byteStr == STATUS_SUCCESS || byteStr == STATUS_DOING) {
                        order.success(BleProfile.BEE_TAG, statusCode(byteValue))
                    } else {
                        order.fail(BleProfile.BEE_TAG, byteValue)
                    }
                } else {
                    order.fail(BleProfile.BEE_TAG, "失败")
                }
            } else {                                                                                //丁丁设备
                order.success(BleProfile.BEE_TAG, lockStatusForDD(BleProfile.BEE_TAG, data))
            }
        }

        /**
         * 地锁起降状态返回
         */
        private fun resultUpDownStatus(a: Int?, order: BleOrderIml?, data: ByteArray?, mBleMsgValue: LockMesBean?) {
            if (mBleMsgValue?.model?.line?.toString() == BleProfile.LOCK_XJ_TAG) {              //洛可可设备
                val byteStr = ByteUtils.toHexString1(data!![2])
                val byteValue = statusCode(byteStr)
                if (byteStr == STATUS_SUCCESS || byteStr == STATUS_DOING) {
                    if (a == 1) {
                        order?.success(BleProfile.UP_TAG, BleProfile.UP_TAG + byteValue)
                    } else {
                        order?.success(BleProfile.DOWN_TAG, BleProfile.DOWN_TAG + byteValue)
                    }
                }
            } else {                                                                                //丁丁设备
                if (a == 1) {
                    order?.success(BleProfile.UP_TAG, lockStatusForDD(BleProfile.UP_TAG, data))
                } else {
                    order?.success(BleProfile.DOWN_TAG, lockStatusForDD(BleProfile.DOWN_TAG, data))
                }
            }
        }

        /**
         * 错误码处理
         */
        private fun statusCode(str: String?): String {
            when (str) {
                STATUS_SUCCESS -> return "成功"
                STATUS_UNDER_ERROR -> return "未知错误"
                STATUS_DOING -> return "正在处理"
                STATUS_INVALID -> return "无效"
                STATUS_PARAMS_ERROR -> return "参数不合法"
                STATUS_LENTH_ERROR -> return "长度不合法"
                STATUS_PWD_ERROR -> return "密码错误"
                STATUS_ORDER_ERROR -> return "不支持的命令"
                STATUS_TYPE_ERROR -> return "类型不匹配"
                STATUS_VERSION_ERROR -> return "版本不匹配"
                STATUS_NOFOUND_ERROR -> return "找不到设备"
                STATUS_CHECK_ERROR -> return "校验和不匹配"
                STATUS_PERMISS_ERROR -> return "权限拒绝"
                STATUS_CLEAN_ERROR -> return "擦除存储器失败"
                STATUS_WRITE_ERROR -> return "写存储器失败"
                STATUS_READ_ERROR -> return "读存储器失败"
                STATUS_MATCH_ERROR -> return "不匹配"
            }
            return "未知错误"
        }

        /**
         * DD地锁状态解析
         */
        private fun lockStatusForDD(type: String?, data: ByteArray?): String {
            val str = ByteUtils.toHexStringArr(data)
            when (type) {
                BleProfile.STATUS_TAG -> {                                  //状态值判断
                    val lockMsg: HashMap<String, String> = HashMap()
                    when (str[7]) {
                        "02" -> {                               //地锁状态
                            when (str[8]) {
                                "01" -> lockMsg["地锁状态"] = "已落锁"
                                "02" -> lockMsg["地锁状态"] = "已抬锁"
                            }
                            lockMsg["电量"] = "" + Integer.parseInt(str[9], 16) / 20
                            when (str[10]) {
                                "01" -> lockMsg["车辆状态"] = "有车辆"
                                "02" -> lockMsg["车辆状态"] = "未知"
                                "ff" -> lockMsg["车辆状态"] = "无车辆"
                            }
                            when (str[11]) {
                                "01" -> lockMsg["地锁位置信息"] = "锐角状态"
                                "02" -> lockMsg["地锁位置信息"] = "密码错误"
                                "03" -> lockMsg["地锁位置信息"] = "上锁垂直位置"
                                "10" -> lockMsg["地锁位置信息"] = "钝角状态"
                                "11" -> lockMsg["地锁位置信息"] = "解锁平躺位置"
                                "ee" -> lockMsg["地锁位置信息"] = "地锁故障"
                            }
                        }
                    }
                    return Gson().toJson(lockMsg).toString()
                }

                BleProfile.UP_TAG, BleProfile.DOWN_TAG -> {                    //升降状态返回值处理
                    when (str[10]) {
                        "02" -> return "密码错误"
                        "03" -> return "$type 成功"
                        "04" -> return "$type 失败"
                        "ee" -> return "地锁故障"
                    }
                }

                BleProfile.BEE_TAG -> {                                           //蜂鸣返回值处理
                    when (str[10]) {
                        "02" -> return "KEY错误"
                        "03" -> return "$type 成功"
                        "04" -> return "$type 失败"
                    }
                }
            }
            return "未知错误"
        }

        /**
         * LKK地锁状态解析
         */
        private fun lockStatus(type: String?, data: ByteArray?): String? {
            if (data != null) {
                val lockMsg: HashMap<String, String> = HashMap()
                when (type) {
                    "状态" -> {
                        when (ByteUtils.toHexString1(data[3])) {
                            "00" -> lockMsg["地锁状态"] = "地锁状态未知"
                            "01" -> lockMsg["地锁状态"] = "已落锁"
                            "02" -> lockMsg["地锁状态"] = "已抬锁"
                            "03" -> lockMsg["地锁状态"] = "已落锁"
                            "04" -> lockMsg["地锁状态"] = "已抬锁"
                        }
                        lockMsg["电量"] = (Math.abs(data[4].toFloat()) / 20).toString()

                        when (ByteUtils.toHexString1(data[5])) {
                            "01" -> lockMsg["车辆状态"] = "有车辆"
                            "02" -> lockMsg["车辆状态"] = "未知"
                            "ff" -> lockMsg["车辆状态"] = "无车辆"
                        }

                        when (ByteUtils.toHexString1(data[6])) {
                            "01" -> lockMsg["地锁位置信息"] = "锐角状态"
                            "03" -> lockMsg["地锁位置信息"] = "上锁垂直位置"
                            "10" -> lockMsg["地锁位置信息"] = "钝角状态"
                            "11" -> lockMsg["地锁位置信息"] = "解锁躺平位置"
                            "EE" -> lockMsg["地锁位置信息"] = "地锁故障"
                        }
                    }
                }
                return Gson().toJson(lockMsg).toString()
            }
            return null
        }

        /**
         * 去除头部命令
         */
        private fun deleteHead(data: ByteArray?): ByteArray? {
            if (data != null) {
                val random = ByteArray(data.size - 2)
                System.arraycopy(data, 2, random, 0, data.size - 2)
                return random
            }
            return null
        }

        /**
         * 鉴权数组合并
         * 转换为md5加密
         */
        private fun authArrayMerge(presetPwd: ByteArray?, randomPwd: ByteArray?, mLockIdStr: ByteArray?): ByteArray? {
            if (presetPwd != null && randomPwd != null && mLockIdStr != null) {
                val random = ByteArray(presetPwd.size + randomPwd.size + mLockIdStr.size)
                System.arraycopy(presetPwd, 0, random, 0, presetPwd.size)
                System.arraycopy(randomPwd, 0, random, presetPwd.size, randomPwd.size)
                System.arraycopy(mLockIdStr, 0, random, presetPwd.size + randomPwd.size, mLockIdStr.size)
                val md5Byte = MD5Tool.md5ToByte(random)

                val md5ByteArr = ByteArray(BleProfile.authBle.size + md5Byte.size)
                System.arraycopy(BleProfile.authBle, 0, md5ByteArr, 0, BleProfile.authBle.size)
                System.arraycopy(md5Byte, 0, md5ByteArr, BleProfile.authBle.size, md5Byte.size)
                return md5ByteArr
            }
            return null
        }

        fun disConnect() {
            BlueToothUtil.getInstance().destoryConn()
        }
    }
}